# pyqt5_qthread_progress.py
import sys
import time
from PyQt5.QtCore import QObject, QThread, pyqtSignal, pyqtSlot, Qt
from PyQt5.QtWidgets import (
    QApplication, QWidget, QVBoxLayout, QHBoxLayout,
    QPushButton, QProgressBar, QLabel
)

class Worker(QObject):
    """在子线程中执行的工作对象"""
    progress = pyqtSignal(int)      # 发射进度 0~100
    message = pyqtSignal(str)       # 状态信息
    finished = pyqtSignal()         # 结束信号（正常完成或被取消）

    def __init__(self, total=100, delay=0.03):
        super().__init__()
        self._total = total
        self._delay = delay
        self._stop = False
        self._paused = False

    @pyqtSlot()
    def run(self):
        self.message.emit("开始执行…")
        for i in range(self._total + 1):
            if self._stop:
                self.message.emit("已取消")
                break

            # 暂停循环
            while self._paused and not self._stop:
                print("dfdafafd ")
                time.sleep(0.05)
            print("1111")
            self.progress.emit(i)
            time.sleep(self._delay)

        self.finished.emit()

    # 以下槽函数供主线程调用，修改运行状态
    @pyqtSlot()
    def pause(self):
        if not self._paused:
            self._paused = True
            self.message.emit("已暂停")

    @pyqtSlot()
    def resume(self):
        if self._paused:
            self._paused = False
            self.message.emit("继续执行…")

    @pyqtSlot()
    def stop(self):
        self._stop = True
        # 若在暂停中，也让其跳出暂停循环
        self._paused = False
        self.message.emit("正在取消…")


class Window(QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("PyQt5 + QThread 进度条示例")
        self.resize(420, 160)

        self.bar = QProgressBar()
        self.bar.setRange(0, 100)
        self.bar.setValue(0)

        self.label = QLabel("就绪")
        self.label.setAlignment(Qt.AlignCenter)

        self.btn_start = QPushButton("开始")
        self.btn_pause = QPushButton("暂停")
        self.btn_resume = QPushButton("继续")
        self.btn_cancel = QPushButton("取消")

        # 初始按钮状态
        self.btn_pause.setEnabled(False)
        self.btn_resume.setEnabled(False)
        self.btn_cancel.setEnabled(False)

        h = QHBoxLayout()
        h.addWidget(self.btn_start)
        h.addWidget(self.btn_pause)
        h.addWidget(self.btn_resume)
        h.addWidget(self.btn_cancel)

        lay = QVBoxLayout(self)
        lay.addWidget(self.bar)
        lay.addWidget(self.label)
        lay.addLayout(h)

        # 连接按钮信号
        self.btn_start.clicked.connect(self.start_task)
        self.btn_pause.clicked.connect(self.pause_task)
        self.btn_resume.clicked.connect(self.resume_task)
        self.btn_cancel.clicked.connect(self.cancel_task)

        # 线程/worker 占位
        self.thread = None
        self.worker = None

    def start_task(self):
        if self.thread is not None:
            return  # 已在运行

        # 创建线程与工作者
        self.thread = QThread()
        self.worker = Worker(total=100, delay=0.03)
        self.worker.moveToThread(self.thread)

        # 线程启动后调用 worker.run
        self.thread.started.connect(self.worker.run)

        # worker 信号回到 UI
        self.worker.progress.connect(self.bar.setValue)
        self.worker.message.connect(self.label.setText)
        self.worker.finished.connect(self.on_finished)

        # 生命周期管理：结束时退出线程
        self.worker.finished.connect(self.thread.quit)

        # 清理：线程结束后删除对象
        self.thread.finished.connect(self.thread.deleteLater)
        self.thread.finished.connect(self._clear_thread_refs)

        # UI 状态
        self.bar.setValue(0)
        self.label.setText("准备开始…")
        self.btn_start.setEnabled(False)
        self.btn_pause.setEnabled(True)
        self.btn_resume.setEnabled(False)
        self.btn_cancel.setEnabled(True)

        self.thread.start()

    def pause_task(self):
        if self.worker:
            self.worker.pause()
            self.btn_pause.setEnabled(False)
            self.btn_resume.setEnabled(True)

    def resume_task(self):
        if self.worker:
            self.worker.resume()
            self.btn_pause.setEnabled(True)
            self.btn_resume.setEnabled(False)

    def cancel_task(self):
        if self.worker:
            self.worker.stop()
            # 等待 on_finished 做 UI 恢复

    @pyqtSlot()
    def on_finished(self):
        self.label.setText("任务结束")
        self.btn_start.setEnabled(True)
        self.btn_pause.setEnabled(False)
        self.btn_resume.setEnabled(False)
        self.btn_cancel.setEnabled(False)

    def _clear_thread_refs(self):
        # 断开与删除 worker 引用（让 Qt 负责回收）
        self.worker.deleteLater()
        self.worker = None
        self.thread = None

    def closeEvent(self, event):
        # 窗口关闭前确保线程安全退出
        if self.worker and self.thread:
            self.worker.stop()
            self.thread.quit()
            self.thread.wait(2000)  # 最多等 2 秒
        event.accept()


if __name__ == "__main__":
    app = QApplication(sys.argv)
    w = Window()
    w.show()
    sys.exit(app.exec_())
